Locate a dataset that you are interested in working with. The data should be sufficiently complex that you can ask lots of questions about it and engage in creative design techniques, but not so complex that you need specialized hardware or algorithmic approaches to analyze. While you are welcome to use any data you’d like, I recommend that your datasets are tabular (e.g., CSV, TSV, SQL, etc.), contain 5,000 or fewer datapoints (on the order of one hundred or so tends to be sufficiently interesting without causing lag in Altair), and is data that you’re comfortable discussing as part of the course (e.g., avoid data that is overly private or classified).
Discuss your dataset, including the data’s source, key attributes/dimensions of the data, and your goals for working with that data (i.e., what are the key questions you want to answer). Identify existing relevant visualizations for working with that data (either using the same data, showing the same concepts, or just that might provide some inspiration) and critique those visualizations based on the practices from this module. What works well? What might need improvement or to change to answer your target questions?
The dataset used is from the Union of Concerned Scientists (UCSUSA) which details all openly-known satellites orbitting the earth at the time of previous update - January 1, 2023.
UCSUSA has a visualization highlighting each country on an image of a map that has satellites or not. They also distinguish between countries that launch satellites or not as well as have a slider depicting the same information from either 1966 or 2020. You can see it at the website above.
Pros:
Cons:
Overall, I believe it to be a successful visualization but has limited uses as it doesn't answer more interesting questions that live within this dataset. Giving the user the ability to reach more information depth through other methods of interaction would help improve this execution.
# Import necessary packages and data.
import pandas as pd
import altair as alt
alt.data_transformers.enable('vegafusion')
from vega_datasets import data
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
sat_df = pd.read_csv('UCS-Satellite-Database-1-1-2023.csv')
country_codes_df = pd.read_csv('iso_3166_country_codes.csv')
# Preliminary EDA
print(sat_df.shape)
print(sat_df.columns)
(6718, 68)
Index(['Name of Satellite, Alternate Names',
'Current Official Name of Satellite', 'Country/Org of UN Registry',
'Country of Operator/Owner', 'Operator/Owner', 'Users', 'Purpose',
'Detailed Purpose', 'Class of Orbit', 'Type of Orbit',
'Longitude of GEO (degrees)', 'Perigee (km)', 'Apogee (km)',
'Eccentricity', 'Inclination (degrees)', 'Period (minutes)',
'Launch Mass (kg.)', ' Dry Mass (kg.) ', 'Power (watts)',
'Date of Launch', 'Expected Lifetime (yrs.)', 'Contractor',
'Country of Contractor', 'Launch Site', 'Launch Vehicle',
'COSPAR Number', 'NORAD Number', 'Comments', 'Unnamed: 28',
'Source Used for Orbital Data', 'Source', 'Source.1', 'Source.2',
'Source.3', 'Source.4', 'Source.5', 'Source.6', 'Unnamed: 37',
'Unnamed: 38', 'Unnamed: 39', 'Unnamed: 40', 'Unnamed: 41',
'Unnamed: 42', 'Unnamed: 43', 'Unnamed: 44', 'Unnamed: 45',
'Unnamed: 46', 'Unnamed: 47', 'Unnamed: 48', 'Unnamed: 49',
'Unnamed: 50', 'Unnamed: 51', 'Unnamed: 52', 'Unnamed: 53',
'Unnamed: 54', 'Unnamed: 55', 'Unnamed: 56', 'Unnamed: 57',
'Unnamed: 58', 'Unnamed: 59', 'Unnamed: 60', 'Unnamed: 61',
'Unnamed: 62', 'Unnamed: 63', 'Unnamed: 64', 'Unnamed: 65',
'Unnamed: 66', 'Unnamed: 67'],
dtype='object')
# Displays the owner of the most currently active satellites.
sat_df.groupby(['Country of Operator/Owner', 'Operator/Owner']).size().sort_values(ascending = False).head(20).reset_index()
| Country of Operator/Owner | Operator/Owner | 0 | |
|---|---|---|---|
| 0 | USA | SpaceX | 3349 |
| 1 | United Kingdom | OneWeb Satellites | 502 |
| 2 | USA | Planet Labs, Inc. | 195 |
| 3 | China | Chinese Ministry of National Defense | 147 |
| 4 | USA | Spire Global Inc. | 127 |
| 5 | Russia | Ministry of Defense | 99 |
| 6 | USA | Swarm Technologies | 84 |
| 7 | USA | Iridium Communications, Inc. | 75 |
| 8 | China | Chang Guang Satellite Technology Co. Ltd. | 53 |
| 9 | USA | National Reconnaissance Office (NRO) | 50 |
| 10 | China | China Academy of Space Technology (CAST) | 49 |
| 11 | USA | Spacex | 46 |
| 12 | India | Indian Space Research Organization (ISRO) | 46 |
| 13 | ESA | European Space Agency (ESA) | 40 |
| 14 | USA | ORBCOMM Inc. | 35 |
| 15 | USA | DoD/US Air Force | 34 |
| 16 | USA | Intelsat S.A. | 34 |
| 17 | USA | Globalstar | 33 |
| 18 | Luxembourg | SES S.A. | 31 |
| 19 | Argentina | Satellogic S.A. | 30 |
# Check all column features for the amount of unique values.
sat_df = sat_df.drop(sat_df.iloc[:, 28:], axis = 1)
for col in sat_df:
print(col, '|', sat_df[col].unique().size)
Name of Satellite, Alternate Names | 6709 Current Official Name of Satellite | 6698 Country/Org of UN Registry | 70 Country of Operator/Owner | 104 Operator/Owner | 639 Users | 20 Purpose | 31 Detailed Purpose | 53 Class of Orbit | 5 Type of Orbit | 9 Longitude of GEO (degrees) | 446 Perigee (km) | 783 Apogee (km) | 777 Eccentricity | 796 Inclination (degrees) | 450 Period (minutes) | 580 Launch Mass (kg.) | 567 Dry Mass (kg.) | 172 Power (watts) | 153 Date of Launch | 1187 Expected Lifetime (yrs.) | 29 Contractor | 560 Country of Contractor | 103 Launch Site | 39 Launch Vehicle | 164 COSPAR Number | 6707 NORAD Number | 6703 Comments | 1288
# Clean up the data for use.
country_codes_df = country_codes_df.rename({'name' : 'Country of Operator/Owner'}, axis = 1)
country_codes_df = country_codes_df.rename({'country-code' : 'Country_Code'}, axis = 1)
# Start with the country codes dataframe to match what is used in the satellite data.
# This will help during the merge to add a country code column for use in maps.
# Should've just changed the .csv at this point but here we are.
country_codes_df.loc[country_codes_df['Country of Operator/Owner'] == 'United States of America', 'Country of Operator/Owner'] = 'USA'
country_codes_df.loc[country_codes_df['Country of Operator/Owner'] == 'United Kingdom of Great Britain and Northern Ireland', 'Country of Operator/Owner'] = 'United Kingdom'
country_codes_df.loc[country_codes_df['Country of Operator/Owner'] == 'Russian Federation', 'Country of Operator/Owner'] = 'Russia'
country_codes_df.loc[country_codes_df['Country of Operator/Owner'] == 'Korea, Republic of', 'Country of Operator/Owner'] = 'South Korea'
country_codes_df.loc[country_codes_df['Country of Operator/Owner'] == 'Taiwan, Province of China', 'Country of Operator/Owner'] = 'Taiwan'
country_codes_df.loc[country_codes_df['Country of Operator/Owner'] == 'Iran (Islamic Republic of)', 'Country of Operator/Owner'] = 'Iran'
country_codes_df.loc[country_codes_df['Country of Operator/Owner'] == "Lao People's Democratic Republic", 'Country of Operator/Owner'] = 'Laos'
country_codes_df.loc[country_codes_df['Country of Operator/Owner'] == 'Viet Nam', 'Country of Operator/Owner'] = 'Vietnam'
country_codes_df.loc[country_codes_df['Country of Operator/Owner'] == 'Venezuela (Bolivarian Republic of)', 'Country of Operator/Owner'] = 'Venezuela'
country_codes_df.loc[country_codes_df['Country of Operator/Owner'] == 'Bolivia (Plurinational State of)', 'Country of Operator/Owner'] = 'Bolivia'
# Satellite df cleaning. Mostly misspellings or duplicate categories.
# Country fixes
sat_df.loc[sat_df['Country of Operator/Owner'] == 'ESA/', 'Country of Operator/Owner'] = 'USA' # This is the Hubble Telescope!
sat_df.loc[sat_df['Country of Operator/Owner'] == 'Czech Republic', 'Country of Operator/Owner'] = 'Czechia'
sat_df.loc[sat_df['Country of Operator/Owner'] == 'China ', 'Country of Operator/Owner'] = 'China'
sat_df.loc[sat_df['Country of Operator/Owner'] == "Sinapore", 'Country of Operator/Owner'] = 'Singapore'
# Operator name fixes.
sat_df.loc[sat_df['Operator/Owner'] == "Spacex", 'Operator/Owner'] = 'SpaceX'
sat_df.loc[sat_df['Operator/Owner'] == "US Air Force ", 'Operator/Owner'] = 'US Air Force'
# Purpose category fixes.
sat_df.loc[sat_df['Purpose'] == "Earth Observation ", 'Purpose'] = 'Earth Observation'
sat_df.loc[sat_df['Purpose'] == "Earth Observation/Navigation", 'Purpose'] = 'Earth Observation'
sat_df.loc[sat_df['Purpose'] == "Communications/Navigation", 'Purpose'] = 'Communications'
sat_df.loc[sat_df['Purpose'] == "Communications/Technology Development", 'Purpose'] = 'Communications'
sat_df.loc[sat_df['Purpose'] == "Earth Observation/Communications/Space Science", 'Purpose'] = 'Earth Observation'
sat_df.loc[sat_df['Purpose'] == "Earth Observation/Space Science", 'Purpose'] = 'Earth Observation'
sat_df.loc[sat_df['Purpose'] == "Space Observation", 'Purpose'] = 'Space Science'
# Class of Orbit fixes.
sat_df.loc[sat_df['Class of Orbit'] == "LEo", 'Class of Orbit'] = 'LEO'
# Remove commas from continuos features as they don't play well with Vega-Altair.
sat_df['Launch Mass (kg.)'] = sat_df['Launch Mass (kg.)'].str.replace(',', '').astype(float)
sat_df['Apogee (km)'] = sat_df['Apogee (km)'].str.replace(',', '').astype(float)
sat_df['Perigee (km)'] = sat_df['Perigee (km)'].str.replace(',', '').astype(float)
sat_df['Period (minutes)'] = sat_df['Period (minutes)'].str.replace(',', '').astype(float)
# Inclination fixes.
sat_df.loc[sat_df['Inclination (degrees)'] == '1,436', 'Inclination (degrees)'] = '1.436'
sat_df.loc[sat_df['Inclination (degrees)'] == "USA", 'Inclination (degrees)'] = '0'
# Users Fixes
sat_df.loc[sat_df['Users'] == 'Military/Commercial', 'Users'] = 'Military'
sat_df.loc[sat_df['Users'] == 'Government/Military', 'Users'] = 'Military'
sat_df.loc[sat_df['Users'] == 'Military/Government', 'Users'] = 'Military'
sat_df.loc[sat_df['Users'] == 'Government/Civil', 'Users'] = 'Government'
sat_df.loc[sat_df['Users'] == 'Military/Civil', 'Users'] = 'Military'
sat_df.loc[sat_df['Users'] == 'Commercial/Civil', 'Users'] = 'Commercial'
sat_df.loc[sat_df['Users'] == 'Civil/Commercial', 'Users'] = 'Civil'
sat_df.loc[sat_df['Users'] == 'Commercial/Government', 'Users'] = 'Government'
sat_df.loc[sat_df['Users'] == 'Government/Commercial/Military', 'Users'] = 'Government'
sat_df.loc[sat_df['Users'] == 'Civil/Government', 'Users'] = 'Civil'
sat_df.loc[sat_df['Users'] == 'Civil/Military', 'Users'] = 'Military'
sat_df.loc[sat_df['Users'] == 'Commercial ', 'Users'] = 'Commercial'
sat_df.loc[sat_df['Users'] == 'Commercial/Military', 'Users'] = 'Military'
sat_df.loc[sat_df['Users'] == 'Government ', 'Users'] = 'Government'
sat_df.loc[sat_df['Users'] == 'Military ', 'Users'] = 'Military'
# Apogee Fixes
sat_df.loc[sat_df['Apogee (km)'] == 353798, 'Apogee (km)'] = 35798 # Checked records, this was listed as GEO which made this apogee nonsense.
# Merge country info with satellite dataframe.
print(country_codes_df.head())
sat_df = sat_df.merge(country_codes_df, on = 'Country of Operator/Owner', how = 'left')
# Display and check if correct.
display(sat_df.head(2))
Country of Operator/Owner alpha-3 Country_Code 0 Afghanistan AFG 4 1 Åland Islands ALA 248 2 Albania ALB 8 3 Algeria DZA 12 4 American Samoa ASM 16
| Name of Satellite, Alternate Names | Current Official Name of Satellite | Country/Org of UN Registry | Country of Operator/Owner | Operator/Owner | Users | Purpose | Detailed Purpose | Class of Orbit | Type of Orbit | ... | Expected Lifetime (yrs.) | Contractor | Country of Contractor | Launch Site | Launch Vehicle | COSPAR Number | NORAD Number | Comments | alpha-3 | Country_Code | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1HOPSAT-TD (1st-generation High Optical Perfor... | 1HOPSAT-TD | NR | USA | Hera Systems | Commercial | Earth Observation | Infrared Imaging | LEO | Non-Polar Inclined | ... | 0.5 | Hera Systems | USA | Satish Dhawan Space Centre | PSLV | 2019-089H | 44859 | Pathfinder for planned earth observation const... | USA | 840.0 |
| 1 | Aalto-1 | Aalto-1 | Finland | Finland | Aalto University | Civil | Technology Development | NaN | LEO | Sun-Synchronous | ... | 2.0 | Aalto University | Finland | Satish Dhawan Space Centre | PSLV | 2017-036L | 42775 | Technology development and education. | FIN | 246.0 |
2 rows × 30 columns
# Ensure all countries have their proper codes by seeing which entries don't have one.
print(sat_df['Country of Operator/Owner'].where(sat_df['Country_Code'].isna()).unique())
[nan 'Multinational' 'ESA' 'USA/Argentina' 'France/Italy' 'China/Brazil' 'China/France' 'USA/Canada/Japan' 'USA/Japan/Brazil' 'USA/Japan' 'USA/Germany' 'France/Italy/Belgium/Spain/Greece' 'Greece/United Kingdom' 'United Kingdom/ESA' 'USA/India/Singapore/Taiwan' 'ESA/Russia' 'USA/France' 'Japan/Singapore' 'United Kingdom/Netherlands' 'Morocco/Germany' 'India/France' 'USA/Canada' 'India/Canada' 'France/Belgium/Sweden' 'Singapore/Taiwan' 'Poland/UK' 'USA/United Kingdom/Italy' 'Turkmenistan/Monaco' 'France/Israel' 'China/Italy']
# Check to see how many satellites are co-owned.
# Will leave these out of the calculation for individual countries for now.
sat_df.loc[sat_df['Country_Code'].isna(), 'Country of Operator/Owner'].size
168
# Check dates datatype for use later.
# Reformat into a datetime format.
print(sat_df['Date of Launch'].dtype)
sat_df.loc[sat_df['Date of Launch'] == '11/29/018', 'Date of Launch'] = '29-11-2018'
sat_df['Date of Launch'] = pd.to_datetime(sat_df['Date of Launch'], format = '%d-%m-%Y', errors = 'raise')
# Create a separate column for year of launch for easier utilization later.
sat_df['Year of Launch'] = pd.DatetimeIndex(sat_df['Date of Launch']).year
# Check date change for sanity check.
print(sat_df.iloc[1070])
object Name of Satellite, Alternate Names Hubble Space Telescope (HST, Space Telescope) Current Official Name of Satellite Hubble Space Telescope Country/Org of UN Registry USA Country of Operator/Owner USA Operator/Owner European Space Agency (ESA)/NASA Users Government Purpose Space Science Detailed Purpose NaN Class of Orbit LEO Type of Orbit Non-Polar Inclined Longitude of GEO (degrees) 0.0 Perigee (km) 555.0 Apogee (km) 559.0 Eccentricity 0.000289 Inclination (degrees) 28.5 Period (minutes) 95.8 Launch Mass (kg.) 11110.0 Dry Mass (kg.) NaN Power (watts) 2,400.00 Date of Launch 1990-04-25 00:00:00 Expected Lifetime (yrs.) 10.0 Contractor European Space Agency/NASA Country of Contractor International Launch Site Cape Canaveral Launch Vehicle Space Shuttle (STS 31) COSPAR Number 1990-037B NORAD Number 20580 Comments Exploration of space. alpha-3 USA Country_Code 840.0 Year of Launch 1990 Name: 1070, dtype: object
Your Module 1 discussion post identified some high-level goals for working with a dataset of interest to you. In this post, you will expand on those goals to characterize your target problem and develop some low-fidelity prototypes for working with that data. First, identify two to three tasks you would wish to complete with your data, identifying:
Why is a task pursued? (goal)
How is a task conducted? (means)
What does a task seek to learn about the data? (characteristics)
Where does the task operate? (target data)
When is the task performed? (workflow)
Who is executing the task? (roles)
Then, sketch a set of preliminary low-fidelity prototypes for addressing these tasks with the given data. You may either sketch freeform or use the Five Design Sheets approach to generate these prototypes (hand-sketched on paper is fine). Upload a copy of your sketches as part of your post.
Using the information gained by the high-level exploratory data analysis performed in part 1, the examples found from the data source, and preliminary sketching done for possible tasks we will now flesh out the tasks for this data.
Task 1: Data overview displaying key features organized by country.
Task 2: Using dates of launch and life expectancy, display age statistics across features
Task 3: Calculate and visualize orbital paths of active satellites.
# Let's see what the data looks like organized and sorted by country and total count.
print(sat_df.groupby(['Country of Operator/Owner', 'alpha-3', 'Country_Code']).size().sort_values(ascending = False).head(20))
Country of Operator/Owner alpha-3 Country_Code USA USA 840.0 4512 China CHN 156.0 587 United Kingdom GBR 826.0 561 Russia RUS 643.0 177 Japan JPN 392.0 88 India IND 356.0 59 Canada CAN 124.0 56 Germany DEU 276.0 48 Luxembourg LUX 442.0 45 Argentina ARG 32.0 38 Israel ISR 376.0 27 Spain ESP 724.0 26 France FRA 250.0 24 Finland FIN 246.0 23 South Korea KOR 410.0 21 Italy ITA 380.0 15 Switzerland CHE 756.0 15 Netherlands NLD 528.0 14 Australia AUS 36.0 14 Brazil BRA 76.0 14 dtype: int64
country_select = alt.selection_point(fields = ['Country of Operator/Owner'], value = 'USA')
country_title = alt.TitleParams('Total Number of Active Satellites by Country',
subtitle = ['Filter Country by clicking on corresponding bar.', '(Source Data Updated 1/2023)'])
# Country totals graph.
# Added interactivity to select country and show 3 graphs.
country_bar_graph = alt.Chart(sat_df, title = country_title
).transform_aggregate(
groupby = ['Country of Operator/Owner'],
count = 'count()'
).transform_window(
rank = 'rank(count)',
sort = [alt.SortField('count', order = 'descending')]
).transform_filter(
(alt.datum.rank <= 29) #29
).mark_bar().encode(
x = alt.X('Country of Operator/Owner:N',
sort = '-y'),
y = alt.Y('count:Q', title = 'Number of Satellites (Log Scale)').scale(type = 'log'),
color = alt.Color('Country of Operator/Owner:N', legend = None),#.scale(scheme = 'tableau20'),
stroke = alt.condition(country_select, alt.ColorValue('black'), alt.Color('Country of Operator/Owner:N', legend = None)),
strokeWidth = alt.condition(country_select, alt.value(1), alt.value(0.5)),
text = alt.Text('count:Q'),
opacity = alt.condition(country_select, alt.value(0.7), alt.value(0.4))
).add_params(country_select)#.properties(width = 1000)
# Selected country's operator/owner graph.
operator_title = alt.TitleParams('Number of Satellites by Operator/Owner')
operator_bar_graph = alt.Chart(sat_df, title = operator_title
).mark_bar().encode(
y = alt.Y('Operator/Owner:N',
sort = '-x'),
x = alt.X('count():Q'),
text = alt.Text('count():Q'),
color = alt.Color('count():O', legend = None).scale(scheme = 'warmgreys')
).transform_filter(country_select)
# Selected country's purpose of satellite graph.
purpose_title = alt.TitleParams('Number of Satellites by Functionality')
purpose_bar_graph = alt.Chart(sat_df, title = purpose_title
).mark_bar().encode(
x = alt.X('Purpose:N',
sort = '-y'),
y = alt.Y('count():Q'),
text = alt.Text('count():Q'),
color = alt.Color('count():O', legend = None).scale(scheme = 'warmgreys')
).transform_filter(country_select)
# Selected country's Users of satellite graph.
users_title = alt.TitleParams('Number of Satellites by Primary User')
users_bar_graph = alt.Chart(sat_df, title = users_title
).mark_bar().encode(
x = alt.X('Users:N',
sort = '-y'),
y = alt.Y('count():Q'),
text = alt.Text('count():Q'),
color = alt.Color('count():O', legend = None).scale(scheme = 'warmgreys')
).transform_filter(country_select)
# Selected country's launches per year.
year_title = alt.TitleParams('Number of Satellites Launched per Year')
year_bar_graph = alt.Chart(sat_df, title = year_title
).mark_bar().encode(
y = alt.Y('Year of Launch:O',
axis = alt.Axis(orient = 'right'), scale = alt.Scale(reverse = True)),
x = alt.X('count():Q', scale = alt.Scale(reverse = True)),
text = alt.Text('count():Q'),
color = alt.condition(alt.datum.count == 0, alt.value('blue'), 'count():O', legend = None)
).transform_filter(country_select)
country_bar_graph = country_bar_graph + country_bar_graph.mark_text(align = 'center', dy = -14, fontSize = 9)
operator_bar_graph = operator_bar_graph + operator_bar_graph.mark_text(align = 'center', dx = 14, fontSize = 9)
users_bar_graph = users_bar_graph + users_bar_graph.mark_text(align = 'center', dy = -14, fontSize = 9)
purpose_bar_graph = purpose_bar_graph + purpose_bar_graph.mark_text(align = 'center', dy = -14, fontSize = 9)
year_bar_graph = year_bar_graph + year_bar_graph.mark_text(align = 'center', dx = -14, fontSize = 9)
(country_bar_graph) & (users_bar_graph | purpose_bar_graph | year_bar_graph| operator_bar_graph)
# sat_df[sat_df['Operator/Owner'].str.contains('National Aeronautics and Space')]
sat_df.loc[sat_df['Country of Operator/Owner'] == 'USA', 'Operator/Owner'].unique()
array(['Hera Systems', 'National Reconnaissance Office (NRO)',
'US Air Force', 'Department of Homeland Security',
'Aerospace Corporation',
'Center for Atmospheric Sciences, Hampton University/NASA',
'US Air Force Institute of Technology', 'SES S.A.',
'SES S.A./Gogo', 'AMSAT-NA', 'ANDESITE - Boston University',
'University of South Florida, Institute of Applied Engineering (IAE).',
'Planetary Resources', '1Worldspace', 'Astranis', 'DirecTV, Inc.',
'PointView Tech', 'Salish Kootenai College', 'BlackSky Global',
'AST SpaceMobile', 'SpaceQuest, Ltd.',
'Capital Technology University',
'University of Louisiana at Lafayette', 'Capella Space',
'Air Force Research Laboratory',
'NASA Goddard Space Flight Center',
'Defense Innovation Unit/Cesium Astro',
'National Aeronautics and Space Administration (NASA) Goddard Space Flight Center',
'University of Florida', 'GeoOptics Inc.', 'GeoOptics, Inc.',
'University of California-Berkeley/Imperial College-London',
'Utah State University', 'Unknown US agency',
'National Aeronautics and Space Administration (NASA)/Colorado State University',
'Department of Defense/Missile Defense Agency',
'US Air Force/ US Navy/NASA', 'Astro Digital',
'California Polytechnic State University/NASA JPL',
'University of Colorado',
'University of Illinois Urbana-Champaign',
'National Aeronautics and Space Administration (NASA)',
'Department of Astrophysical and Planetary Science, UC Boulder/National Aeronautics and Space Administration (NASA)',
'University of Michigan/NASA Earth Science Technology Office',
'North Idaho STEM Charter Academy',
'Massachusetts Institute of Technology',
'DARPA (Defense Advanced Research Projects Agency)', 'DoD/NOAA',
'University of Southern California, Space Engineering Research Center/Lockheed Martin',
'Planet Labs, Inc.', 'Global Eagle Entertainment',
'Echostar Satellite Services, LLC',
'HughesNet leased from Echostar Technologies, LLC',
'Echostar Satellite Services, LLC/Intelsat ', 'Momentus',
'University of California',
'Goddard Space Flight Center/EOS Data and Operations System',
'ESPACE', 'Defense Advanced Research Projects Agency (DARPA)',
'California Polytechnic Institute', 'US Air Force Academy',
'University of Texas - Austin',
'National Aeronautics and Space Administration (NASA)/GSFC',
'Firebird Consortium (Montana State Univ., Univ. of New Hampshire, Aerospace Corp., Los Alamos National Laboratory)',
'US Navy', 'Los Alamos National Laboratory',
'PanAmSat (Intelsat S.A.)', 'Intelsat S.A.', 'Intelsat S.A. ',
'PanAmSat (Intelsat S.A.)/DirecTV, Inc.',
'Air Force Research Laboratory/Globalstar',
'NearSpace Launch/Air Force Research Laboratory',
'Bigelow Aerospace', 'DigitalGlobe Corporation', 'Globalstar',
'PlanetiQ',
'NOAA (National Oceanographic and Atmospheric Administration)',
'Lunasonde', 'Air Force Satellite Control Network',
'U.S. Army�s Space and Missile Defense Command',
'Department of Defense/Army Space and Missile Defense Command',
'Department of Defense/Space Test Program',
'US Army Space and Missile Defense Command', 'HawkEye 360',
'Space Sciences Laboratory, UC Berkeley/NASA',
'Harris Corporation', 'European Space Agency (ESA)/NASA',
'Intelsat S.A./Sky Perfect JSAT Corp.',
'National Aeronautics and Space Administration (NASA)/Goddard Space Flight Center',
'Iridium Communications, Inc.',
'NASA Small Satellite Technology Program', 'NASA/CalPoly',
'US Army Space and Missile Defense Command/Army Forces Strategic Command',
'National Aeronautics and Space Administration (NASA)/US Geological Survey',
'US Space Force', 'Spire Global Inc.',
'California Polytechnic State University',
'General Atomics Electromagnetic Systems', 'Lynk Global Inc.',
'Northwest Nazarene University',
'University of Michigan/Montana University',
'National Reconnaissance Office (NRO)/US Air Force',
'Analytical Space', 'Space Logistics LLC',
'MIT/Lincoln Laboratory-University of Massachusetts Amherst',
'DoD/US Navy', 'ACMEO', 'Tyvak Nanosatellite Systems, Inc.',
'DoD/US Air Force',
'National Oceanographic and Atmospheric Administration (NOAA) (part of international program)',
'National Oceanographic and Atmospheric Administration (NOAA)/NASA',
'F Space Test Office',
'National Aeronautics and Space Administration (NASA)-Ames Research Center/Stanford University',
'Michigan Technological University/Air Force Research Laboratory',
'U.S. Space Force', 'ORBCOMM Inc.',
'University of Texas at El Paso', 'DARPA/Tethers Unlimited',
'Portland State Aerospace Society',
'F /ORSO (Operationally Responsive Space Office)',
'General Atomics - Electromagnetic Systems Group',
'National Reconnaissance Office',
'National Aeronautics and Space Administration (NASA)/Cornell University',
'US Naval Academy', 'Helios Wire/Echostar Global Australia',
'Tiger Innovations', 'Brigham Young University', 'US Coast Guard',
'University of Colorado, Boulder', 'Naval Post-Graduate School',
'Georgia Institute of Technology',
'SES S.A. -- total capacity leased to subsidiary of EchoStar Corp. ',
'Vanderbilt University/AMSAT',
'Robertsville Middle School, Oak Ridge, Tennessee',
'Applied Physics Laboratory/NASA',
'Strategic Space Command/Space Surveillance Network',
'National Reconnaissance Office (NRO)/US Navy',
'University of North Carolina - Wilmington',
'NASA Langley Research Center', 'SRI International',
'Sirius XM Holdings', 'XM Satellite Radio ', 'LightSquared',
'US Southern Command',
'National Aeronautics and Space Administration (NASA) Earth Science Office/Laboratory for Atmospheric and Space Physics, Univ. of Colorado',
'COSMIAC (Configurable Space Microsystems Innovations & Applications Center) ',
'Swarm Technologies', 'Hughes Space and Communications Co. ',
'Omnispace', 'SpaceX', 'Atlas 5', 'Missile Defense Agency (MDA)',
'Naval Research Laboratory',
'Operational Responsive Space (ORS) Office', 'Orbit Fab',
'National Aeronautics and Space Administration (NASA)/SES Americom (SES [Soci�t� Europ�enne des Satellites (SES)])',
'National Aeronautics and Space Administration (NASA)/Ames Research Center',
'Colorado State University', 'TerraStar Corporation',
'National Aeronautics and Space Administration (NASA)/Applied Physics Laboratory, Johns Hopkins',
'UMBRA',
'National Aeronautics and Space Administration (NASA)/Johns Hopkins University Applied Physics Laboratory',
'Care Weather Technologies', 'ViaSat, Inc.',
'NASA/Carnegie Mellon University',
'Military Satellite Communications - US Air Force',
'WildBlue Communications', 'Maxar Technologies Inc.',
'Loft Orbital/Fugro', 'Loft Orbital'], dtype=object)
sat_df['Age_Remaining'] = (sat_df['Year of Launch'] + sat_df['Expected Lifetime (yrs.)']) - 2023
sat_df.sort_values('Age_Remaining')
| Name of Satellite, Alternate Names | Current Official Name of Satellite | Country/Org of UN Registry | Country of Operator/Owner | Operator/Owner | Users | Purpose | Detailed Purpose | Class of Orbit | Type of Orbit | ... | Country of Contractor | Launch Site | Launch Vehicle | COSPAR Number | NORAD Number | Comments | alpha-3 | Country_Code | Year of Launch | Age_Remaining | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 755 | FLTSATCOM-8 (USA 46) | USA 46 | USA | USA | US Navy | Military | Communications | NaN | GEO | NaN | ... | USA | Cape Canaveral | Atlas Centaur | 1989-077A | 20253 | Old system replaced by UFO satellites; this sa... | USA | 840.0 | 1989 | -29.0 |
| 2565 | SCD-1 (Sat�lite de Coleta de Dados) | SCD-1 | Brazil | Brazil | Instituto Nacional de Pesquisas Espaciais (INPE) | Government | Earth Observation | Meteorology/Earth Science | LEO | Non-Polar Inclined | ... | Brazil | Cape Canaveral | Pegasus | 1993-009B | 22491 | Collects meteorological and environmental data... | BRA | 76.0 | 1993 | -27.0 |
| 2683 | Skynet 4C | Skynet 4C | United Kingdom | United Kingdom | Intelsat/Paradigm Secure Communications (wholl... | Military | Communications | NaN | GEO | NaN | ... | France/UK/Germany | Guiana Space Center | Ariane 44LP | 1990-079A | 20776 | Spare. In March 2010 it was announced that the... | GBR | 826.0 | 1990 | -26.0 |
| 6298 | TDRS-3 (Tracking and Data Relay Satellite, TDR... | TDRS-3 | USA | USA | National Aeronautics and Space Administration ... | Government | Communications | NaN | GEO | NaN | ... | USA | Cape Canaveral | Space Shuttle (STS 26) | 1988-091B | 19548 | Backup; still partially operational. | USA | 840.0 | 1988 | -25.0 |
| 6440 | UFO-4 (USA 108, UFO F4 EHF) "UHF Follow-On" | USA 108 | USA | USA | US Navy | Military | Communications | NaN | GEO | NaN | ... | USA | Cape Canaveral | Atlas 2 | 1995-003A | 23467 | Ultra-High Frequency (UHF) communications and ... | USA | 840.0 | 1995 | -24.0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 6710 | Zhuhai 1-06 (OHS-3) | OHS-3 | China | China | Zhuhai Orbita Aerospace Science and Technology... | Commercial | Earth Observation | Hyperspectral Imaging | LEO | Sun-Synchronous | ... | China | Jiuquan Satellite Launch Center | Long March 11 | 2018-040D | 43442 | Survey natural resources, cities, crops and fo... | CHN | 156.0 | 2018 | NaN |
| 6711 | Zhuhai 1-07 (OHS-4) | OHS-4 | China | China | Zhuhai Orbita Aerospace Science and Technology... | Commercial | Earth Observation | Hyperspectral Imaging | LEO | Sun-Synchronous | ... | China | Jiuquan Satellite Launch Center | Long March 11 | 2018-040E | 43443 | Survey natural resources, cities, crops and fo... | CHN | 156.0 | 2018 | NaN |
| 6712 | Ziyuan 1-02C | Ziyuan 1-02C | China | China | China Centre for Resources Satellite Data and ... | Government | Earth Observation | Optical Imaging | LEO | Sun-Synchronous | ... | China | Taiyuan Launch Center | Long March 4B | 2011-079A | 38038 | Can acquire high-resolution data through remot... | CHN | 156.0 | 2011 | NaN |
| 6716 | Ziyuan 3-3 | Ziyuan 3-3 | China | China | China Centre for Resources Satellite Data and ... | Government | Earth Observation | Optical Imaging | LEO | Sun-Synchronous | ... | China | Taiyuan Launch Center | Long March 4B | 2020-051A | 45939 | Land survey satellite. Provide data for the co... | CHN | 156.0 | 2020 | NaN |
| 6717 | Z-Sat | Z-Sat | NR (1/22) | Japan | Mitsubishi Heavy Industries | Commercial | Technology Development | NaN | LEO | Sun-Synchronous | ... | Japan | Uchinoura Space Center | H2A | 2021-102E | 49399 | Testbed for a miniature lab module that could ... | JPN | 392.0 | 2021 | NaN |
6718 rows × 32 columns
sat_df.iloc[1070]
Name of Satellite, Alternate Names Hubble Space Telescope (HST, Space Telescope) Current Official Name of Satellite Hubble Space Telescope Country/Org of UN Registry USA Country of Operator/Owner USA Operator/Owner European Space Agency (ESA)/NASA Users Government Purpose Space Science Detailed Purpose NaN Class of Orbit LEO Type of Orbit Non-Polar Inclined Longitude of GEO (degrees) 0.0 Perigee (km) 555.0 Apogee (km) 559.0 Eccentricity 0.000289 Inclination (degrees) 28.5 Period (minutes) 95.8 Launch Mass (kg.) 11110.0 Dry Mass (kg.) NaN Power (watts) 2,400.00 Date of Launch 1990-04-25 00:00:00 Expected Lifetime (yrs.) 10.0 Contractor European Space Agency/NASA Country of Contractor International Launch Site Cape Canaveral Launch Vehicle Space Shuttle (STS 31) COSPAR Number 1990-037B NORAD Number 20580 Comments Exploration of space. alpha-3 USA Country_Code 840.0 Year of Launch 1990 Age_Remaining -23.0 Name: 1070, dtype: object
(1990+10)-2023
-23
age_chart = alt.Chart(sat_df
).mark_boxplot().encode(
x=alt.X('Purpose'),
y=alt.Y('Age_Remaining'),
color = 'Purpose:N',
tooltip=['Country of Operator/Owner','Current Official Name of Satellite','Date of Launch']
)
age_chart
age_chart_2 = alt.Chart(sat_df
).mark_point().encode(
x=alt.X('Date of Launch'),
y=alt.Y('Age_Remaining'),
color = 'Purpose:N',
tooltip=['Country of Operator/Owner','Current Official Name of Satellite','Purpose', 'Date of Launch', 'Age_Remaining']
)
age_chart_2
age_chart_3 = alt.Chart(sat_df
).mark_boxplot().encode(
x=alt.X('Class of Orbit'),
y=alt.Y('Age_Remaining'),
color = 'Class of Orbit:N',
tooltip=['Country of Operator/Owner','Current Official Name of Satellite','Date of Launch']
)
age_chart_3
age_chart_4 = alt.Chart(sat_df
).mark_boxplot().encode(
x=alt.X('Country of Operator/Owner'),
y=alt.Y('Age_Remaining'),
color = alt.Color('Country of Operator/Owner:N', legend = None),
tooltip=['Country of Operator/Owner','Current Official Name of Satellite','Date of Launch', 'Age_Remaining']
)
age_chart_4
top_k_grouped = sat_df.groupby('Country of Operator/Owner').size().reset_index(name = 'count').sort_values(by = 'count', ascending = False)
top_k_sat_df = pd.merge(top_k_grouped.head(10), sat_df, on = 'Country of Operator/Owner')
top_k_sat_df
| Country of Operator/Owner | count | Name of Satellite, Alternate Names | Current Official Name of Satellite | Country/Org of UN Registry | Operator/Owner | Users | Purpose | Detailed Purpose | Class of Orbit | ... | Country of Contractor | Launch Site | Launch Vehicle | COSPAR Number | NORAD Number | Comments | alpha-3 | Country_Code | Year of Launch | Age_Remaining | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | USA | 4512 | 1HOPSAT-TD (1st-generation High Optical Perfor... | 1HOPSAT-TD | NR | Hera Systems | Commercial | Earth Observation | Infrared Imaging | LEO | ... | USA | Satish Dhawan Space Centre | PSLV | 2019-089H | 44859 | Pathfinder for planned earth observation const... | USA | 840.0 | 2019 | -3.5 |
| 1 | USA | 4512 | Advanced Orion 10 (Mentor, NRO L-44, USA 311) | USA 311 | USA | National Reconnaissance Office (NRO) | Military | Earth Observation | Electronic Intelligence | GEO | ... | USA | Cape Canaveral | Delta 4 Heavy | 2020-095A | 47237 | ELINT. | USA | 840.0 | 2020 | NaN |
| 2 | USA | 4512 | Advanced Orion 4 (Mentor, NROL 6, USA 139) | USA 139 | USA | National Reconnaissance Office (NRO) | Military | Earth Observation | Electronic Intelligence | GEO | ... | USA | Cape Canaveral | Titan IVA | 1998-029A | 25336 | ELINT. | USA | 840.0 | 1998 | NaN |
| 3 | USA | 4512 | Advanced Orion 5 (Mentor, NROL 19, USA 171) | USA 171 | USA | National Reconnaissance Office (NRO) | Military | Earth Observation | Electronic Intelligence | GEO | ... | USA | Cape Canaveral | Titan IV | 2003-041A | 27937 | Electronic intelligence (ELINT). | USA | 840.0 | 2003 | NaN |
| 4 | USA | 4512 | Advanced Orion 6 (Mentor, NRO L-26, USA 202) | USA 202 | USA | National Reconnaissance Office (NRO) | Military | Earth Observation | Electronic Intelligence | GEO | ... | USA | Cape Canaveral | Delta 4 Heavy | 2009-001A | 33490 | ELINT. | USA | 840.0 | 2009 | NaN |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 6207 | Germany | 48 | TET-1 (Technologieerprobungstr�ger 1, Technolo... | TET-1 | Germany | German Aerospace Center (DLR) | Commercial | Technology Development | NaN | LEO | ... | Germany | Baikonur Cosmodrome | Soyuz-Fregat | 2012-039D | 38710 | Center of the OOV (On Orbit Verification) Prog... | DEU | 276.0 | 2012 | -10.0 |
| 6208 | Germany | 48 | TRSI-2 | TRSI-2 | NR(9/22) | MyRadar | Commercial | Technology Development | NaN | LEO | ... | Germany/ | Rocket Lab Launch Complex 1 | Electron | 2022-047AC | 52420 | NaN | DEU | 276.0 | 2022 | 0.0 |
| 6209 | Germany | 48 | TRSI-3 | TRSI-3 | NR (9/22) | MyRadar | Commercial | Technology Development | NaN | LEO | ... | Germany/ | Rocket Lab Launch Complex 1 | Electron | 2022-047AA | 52418 | NaN | DEU | 276.0 | 2022 | 0.0 |
| 6210 | Germany | 48 | TUBIN (Technische Universit�t Berlin) | TUBIN | NR (9/21) | Technical University Berlin | Civil | Technology Demonstration | NaN | LEO | ... | Germany | Cape Canaveral | Falcon 9 | 2021-059X | 48900 | Primary objective to provide an on-orbit demon... | DEU | 276.0 | 2021 | NaN |
| 6211 | Germany | 48 | UWE-4 (University of W�rzburg Experimental Sat... | UWE-4 | Germany | University of W�rzburg | Civil | Technology Development/Educational | NaN | LEO | ... | Germany | Vostochny Cosmodrome | Soyuz-2.1a | 2018-111E | 43880 | Demonstrate miniaturized electric propulsion s... | DEU | 276.0 | 2018 | NaN |
6212 rows × 33 columns
age_chart_facet = alt.Chart(top_k_sat_df).mark_boxplot(ticks = True).encode(
x = alt.X("Users:O",
title = None,
axis = alt.Axis(labels = False, ticks = False),
scale = alt.Scale(padding = 0.75)),
y = alt.Y("Age_Remaining:Q"),
color = alt.Color("Users:N",
legend = alt.Legend(
orient = 'none',
legendX = 350, legendY = -40,
direction = 'horizontal',
titleAnchor = 'middle')),
tooltip=['Country of Operator/Owner','Current Official Name of Satellite', 'Purpose', 'Date of Launch', 'Age_Remaining'])
# Create line to highlight 0 on y-axis.
line_plot = alt.Chart().mark_rule(color= 'black', opacity = 0.02
).encode(y = alt.Y('a:Q'))
alt.layer(age_chart_facet, line_plot, data = top_k_sat_df).facet(
column = alt.Column('Country of Operator/Owner:N',
sort = ['USA'],
header = alt.Header(orient='bottom'))
).configure_facet(
spacing = 0
).transform_calculate(
a = '0'
).display()
age_chart_5 = alt.Chart(sat_df
).mark_boxplot().encode(
x=alt.X('Users'),
y=alt.Y('Age_Remaining'),
color = alt.Color('Users:N', legend = None),
tooltip=['Country of Operator/Owner','Current Official Name of Satellite','Date of Launch', 'Age_Remaining']
)
age_chart_5
alt_chart = alt.Chart(sat_df
).mark_point().encode(
x=alt.X('Perigee (km)'),
y=alt.Y('Apogee (km)'),
color = alt.Color('Class of Orbit:N'),
opacity = alt.value(0.4),
tooltip=['Country of Operator/Owner','Current Official Name of Satellite','Perigee (km)','Apogee (km)','Class of Orbit']
)
alt_chart
period_chart = alt.Chart(sat_df
).mark_boxplot().encode(
x=alt.X('Class of Orbit'),
y=alt.Y('Period (minutes)'),
color = 'Class of Orbit:N',
tooltip=['Country of Operator/Owner','Current Official Name of Satellite','Perigee (km)','Apogee (km)','Class of Orbit']
)
period_chart
# map_df = sat_df.groupby(['Country of Operator/Owner', 'Country_Code']).size().sort_values(ascending = False).reset_index(name = 'count')
display(map_df)
# Map visualization to come later.
| Country of Operator/Owner | Country_Code | count | |
|---|---|---|---|
| 0 | USA | 840.0 | 4512 |
| 1 | China | 156.0 | 587 |
| 2 | United Kingdom | 826.0 | 561 |
| 3 | Russia | 643.0 | 177 |
| 4 | Japan | 392.0 | 88 |
| ... | ... | ... | ... |
| 67 | Hungary | 348.0 | 1 |
| 68 | Nepal | 524.0 | 1 |
| 69 | Iraq | 368.0 | 1 |
| 70 | Jordan | 400.0 | 1 |
| 71 | Kuwait | 414.0 | 1 |
72 rows × 3 columns
earth_radius = 6370
orbits_inc = list(zip(sat_df['Apogee (km)'],
sat_df['Perigee (km)'],
sat_df['Inclination (degrees)'].astype(float),
sat_df['Class of Orbit']))
###
# Resources used:
# https://en.wikipedia.org/wiki/Orbital_elements
# https://en.wikipedia.org/wiki/Two-line_element_set
# Help with inclination orbit rotation - https://space.stackexchange.com/questions/44335/visualising-orbits-from-different-viewpoints-in-python
#
###
def calc_ellipse(apogee, perigee, inclination_deg):
earth_radius = 6370 # km
inclination_rad = np.radians(inclination_deg)
# Adjust altitudes into true apogee (distance to center of earth)
# as data is assuming distance from surface, not center.
apogee_adj = apogee + earth_radius
perigee_adj = perigee + earth_radius
# Calculating semi-major axis and eccentricity (we should check ecc. against data).
a = (apogee_adj + perigee_adj) / 2
e = (apogee - perigee) / (apogee_adj + perigee_adj)
# Generate angles to find ellipse.
angles = np.linspace(0, 2 * np.pi, 1000)
# Calculating distance from Earth center for each angle.
r = (a * (1 - (e ** 2))) / (1 + e * np.cos(angles))
# Converting polar coords to Cartesian coords.
x = r * np.cos(angles)
y = r * np.sin(angles)
# # Rotation matrix for inclination
# # Z
# rotation_matrix = np.array([
# [np.cos(inclination_rad), -np.sin(inclination_rad), 0],
# [np.sin(inclination_rad), np.cos(inclination_rad), 0],
# [0, 0, 1]
# ])
# # X
# rotation_matrix = np.array([
# [1, 0, 0],
# [0, np.cos(inclination_rad), -np.sin(inclination_rad)],
# [0, np.sin(inclination_rad), np.cos(inclination_rad)]
# ])
# Y
rotation_matrix = np.array([
[np.cos(inclination_rad), 0, np.sin(inclination_rad)],
[0, 1, 0],
[-np.sin(inclination_rad), 0, np.cos(inclination_rad)]
])
# Apply inclination to the orbit
orbit = np.array([x, y, np.zeros_like(x)])
rotated_orbit = np.matmul(rotation_matrix, orbit)
x_rot, y_rot, z_rot = rotated_orbit # Don't need z for 2d.
return (x_rot, y_rot)
plt.figure(figsize = (12, 12))
# Plotting the Earth at origin.
earth_circle = plt.Circle((0, 0), earth_radius, color = '#064273', alpha = 1, label = 'Earth')
plt.gca().add_patch(earth_circle)
# Create color mapping.
color_dict = {'Elliptical': '#64113F',
'LEO': '#C73E1D',
'MEO': '#385F71',
'GEO': '#86BAA1'}
for i, j, k, orbit_class in orbits_inc:
x, y = calc_ellipse(i, j, k)
# Plotting the orbit.
plt.plot(x, y, alpha = 0.3, color = color_dict[orbit_class])
plt.title('2D View of Active Satellites Orbiting Earth')
plt.xlabel('X-axis (km)')
plt.ylabel('Y-axis (km)')
plt.grid(True)
plt.axis('equal') # Set an equal aspect ratio
cust_legend = [Line2D([0], [0], color = color_dict['LEO'], lw = 2),
Line2D([0], [0], color = color_dict['MEO'], lw = 2),
Line2D([0], [0], color = color_dict['GEO'], lw = 2),
Line2D([0], [0], color = color_dict['Elliptical'], lw = 2)]
plt.legend(cust_legend, ['Low Earth Orbit (LEO)', 'Middle Earth Orbit (MEO)', 'Geosynchronous Orbit (GEO)', 'Elliptical Orbit'])
plt.show()
from mpl_toolkits.mplot3d import Axes3D
def calc_ellipse_3d(apogee, perigee, inclination_deg):
# Constants
earth_radius = 6370 # km
# Given data
apogee_adj = apogee + earth_radius
perigee_adj = perigee + earth_radius
inclination_rad = np.radians(inclination_deg)
# Calculating semi-major axis and eccentricity
a = (apogee_adj + perigee_adj) / 2
e = (apogee - perigee) / (apogee_adj + perigee_adj)
# Generating angles from 0 to 2*pi
angles = np.linspace(0, 2 * np.pi, 1000)
# Calculating distance from Earth center for each angle
r = (a * (1 - (e ** 2))) / (1 + e * np.cos(angles))
# Converting polar coordinates to Cartesian coordinates
x = r * np.cos(angles)
y = r * np.sin(angles)
# Rotation matrix for inclination
# # Z
# rotation_matrix = np.array([
# [np.cos(inclination_rad), -np.sin(inclination_rad), 0],
# [np.sin(inclination_rad), np.cos(inclination_rad), 0],
# [0, 0, 1]
# ])
# # X
# rotation_matrix = np.array([
# [1, 0, 0],
# [0, np.cos(inclination_rad), -np.sin(inclination_rad)],
# [0, np.sin(inclination_rad), np.cos(inclination_rad)]
# ])
# Y
rotation_matrix = np.array([
[np.cos(inclination_rad), 0, np.sin(inclination_rad)],
[0, 1, 0],
[-np.sin(inclination_rad), 0, np.cos(inclination_rad)]
])
# Apply inclination to the orbit
orbit = np.array([x, y, np.zeros_like(x)])
rotated_orbit = np.matmul(rotation_matrix, orbit)
x_rot, y_rot, z_rot = rotated_orbit
return (x_rot, y_rot, z_rot)
# Creating a 3D plot
fig = plt.figure(figsize = (12, 12))
ax = fig.add_subplot(111, projection = '3d')
# # Plotting Earth
c = [0, 0, 0]
r = [earth_radius] # Radius of earth
u, v = np.mgrid[0:2 * np.pi:50j, 0:np.pi:50j]
x_e = r * np.cos(u) * np.sin(v)
y_e = r * np.sin(u) * np.sin(v)
z_e = r * np.cos(v)
ax.plot_surface(x_e - c[0], y_e - c[1], z_e - c[2], color= '#064273', alpha = 0.2)
# Create color mapping.
color_dict = {'Elliptical': '#64113F',
'LEO': '#C73E1D',
'MEO': '#385F71',
'GEO': '#86BAA1'}
for i, j, k, orbit_class in orbits_inc:
x, y, z = calc_ellipse_3d(i, j, k)
# Plotting the orbit in a side-view perspective
ax.plot(x, y, z, zdir='z', alpha = 0.3, color = color_dict[orbit_class])
# Set labels and title
ax.set_xlabel('X-axis (km)')
ax.set_ylabel('Y-axis (km)')
ax.set_zlabel('Z-axis (km)')
# ax.set_zlim(-360000, 360000)
# ax.set_xlim(-360000, 360000)
# ax.set_ylim(-360000, 360000)
ax.set_box_aspect([1,1,1])
ax.set_aspect('equal')
plt.title('3D View of Active Satellites Orbiting Earth')
#plt.legend()
cust_legend = [Line2D([0], [0], color = color_dict['LEO'], lw = 2),
Line2D([0], [0], color = color_dict['MEO'], lw = 2),
Line2D([0], [0], color = color_dict['GEO'], lw = 2),
Line2D([0], [0], color = color_dict['Elliptical'], lw = 2)]
ax.legend(cust_legend, ['Low Earth Orbit (LEO)', 'Middle Earth Orbit (MEO)', 'Geosynchronous Orbit (GEO)', 'Elliptical Orbit'])
plt.show()
In your previous post, you identified a series of tasks and goals for your visualization as well as some preliminary design ideas. We’ll jump ahead a few steps and start to think about how we might evaluate our design approach. Outline a preliminary evaluation that addresses your core goals with the visualization. Make sure your evaluation discusses:
The target question you want to answer
The people you would recruit to answer that question
The kinds of measures you would use to answer your data (e.g., insight depth, use cases, accuracy) and what these measures would tell you about the core question
The approach you will use to answer that question (e.g., a journaling study, a formal experiment, etc.)
How you would instantiate those methods (i.e., what would your participants do?)
What criteria would you use to indicate that your visualization was successful
Task 1: Data overview displaying key features organized by country.
Task 2: Using dates of launch and life expectancy, display age statistics across features
Task 3: Calculate and visualize orbital paths of active satellites, labeling orbital class.
Throughout the Modules, you have found a dataset, characterized the corresponding goals and tasks you want to conduct with that data, designed preliminary approaches, and outlined how you would evaluate those approaches. For your final project, you will put these ideas into practice by executing on the project plan outlined in your prior posts.
For this project, you will implement a visualization using your data from Module 1 and preliminary low-fidelity prototypes from Module 2 to address your stated goals. You may implement this visualization using either Altair or another platform of your choice. Once implemented, conduct your evaluation based on the plan outlined in your Module 3 discussion post, making sure to conduct your evaluation with at least three people. You may refine any of your prior plan to reflect your evolving understanding of the challenges you are addressing. Be sure to address how your plan has changed from these earlier posts as part of your discussion.
Your final project post should include:
A brief recap of your data, goals, and tasks, focusing on those that most directly influence your design
Screenshots of and/or a link to your visualization implementation (see below for additional guidance)
A summary of the key elements of your design and accompanying justification
A discussion of your final evaluation approach, including the procedure, people recruited, and results. Note that, due to the difficulty of recruiting experts, you can use colleagues, friends, classmates, or family to evaluate your designs if experts or others from your target population are unavailable.
A synthesis of your findings, including what elements of your approach worked well and what elements you would refine in future iterations.
Guidance and platforms for deploying Altair visualizations online include:
Altair: Interactive Plots on the Web
Add Animated Charts To Your Dashboards With Streamlit-Python
Creating Interactive Jupyter Notebooks and Deployment on Heroku Using Voila
Proceed through these questions and
-
-
3.